package com.ydlclass.betterPool;

import com.alibaba.druid.pool.DruidDataSource;

import javax.sql.DataSource;
import java.io.IOException;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.*;

public class BaseDaoImpl<T> implements BetterBaseDao<T> {
    // 设置成保护来，可以被继承的类使用，其他无法使用
    protected static DataSource DATASOURCE = null;

    // 静态代码块，初始化
    static {
        // 1、创建 properties，找到配置文件
        Properties properties = new Properties();
        try {
            properties.load(BaseDaoImpl.class.getClassLoader().getResourceAsStream("jdbc.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 2、创建链接，获取速度快，同时可以大幅度提高数据库访问速度。
        DATASOURCE = new DruidDataSource();
        // 3、配置数据源，将 DATASOURCE 强转成 子类 DruidDataSource
        ((DruidDataSource) DATASOURCE).configFromPropety(properties);

    }


    /**
     * 关闭资源
     * @param connection
     * @param statement
     * @param resultSet
     */
    protected void closeAll(Connection connection, Statement statement, ResultSet resultSet){
        if(connection != null){
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(statement != null){
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(resultSet != null){
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 插入数据
     * @param t  随意处理传入对象的内容
     * @return
     */
    @Override
    public int save(T t) {
        Object object = (Object) t;

        Connection connection = null;
        PreparedStatement statement = null;
        try {
            // 传过来的对象是 user
            // 1.定义sql
            Class<?> aClass = t.getClass();
            String tName = aClass.getName()
                .substring(aClass.getName().lastIndexOf(".") + 1).toLowerCase(); // lastIndexOf 从最后一个 点 开始 截取到最后
            // 获得某个类所有声明的字段，包括public、private和proteced，但不包括父类
            Field[] fields = aClass.getDeclaredFields();

            StringBuilder sql = new StringBuilder();
            sql.append("insert into ").append(tName)
                .append(" value (");
            for (int i = 0; i < fields.length; i++) {
                if(i < fields.length)
                    sql.append("?,");
            }
            sql.append(")");
            String finalSql = sql.toString().replace(",)", ")");
            System.out.println(finalSql);

            // 2.获取链接
            connection = DATASOURCE.getConnection();
            statement =  connection.prepareStatement(finalSql);

            // 3.prepared 设置值
            for (int i = 1; i <= fields.length; i++) {
                fields[i-1].setAccessible(true);  // 获取实体类中的字段需要设值为true,如果不设置在被调用时，会有安全性检测
                if(fields[i-1].getType() == int.class){
                    statement.setInt(i, fields[i-1].getInt(object));
                } else if(fields[i-1].getType() == String.class){
                    statement.setString(i, fields[i-1].get(object).toString());
                }
            }

            // 4.执行
            int rows = statement.executeUpdate();
            return rows;
        } catch (SQLException e){
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } finally {
            closeAll(connection, statement, null);
        }
        return -1;
    }

    /**
     * 根据id来删除数据
     * @param id
     * @return
     */
    @Override
    public int delete(T t, int id) {
        Object object = (Object) t;
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        int restNum = 0;
        // 1、书写sql
        // 获取这个对象的,获取到类的名称
        Class<?> aClass = t.getClass();
        String name = aClass.getName()
            .substring(aClass.getName().lastIndexOf(".")+1).toLowerCase();
//        String sql = "delete from ? where id=?;";
        StringBuilder sql = new StringBuilder();
        sql.append("delete from ").append(name).append(" where id=?");

        // 2.获取链接
        try {
            connection = DATASOURCE.getConnection();
            statement = connection.prepareStatement(sql.toString());
//            statement.setString(1,name.replace("\'",""));
            statement.setInt(1,id);

            statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeAll(connection,statement,resultSet);
        }
        return restNum;
    }

    /**
     * 查询数据
     * @return
     */
    @Override
    public List<T> selectAll(Class clazz) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        List<T> objs = new ArrayList<>();

        try {
            // user
            // sql 获取
            // 获得某个类所有声明的字段，包括public、private和proteced，但不包括父类
            String tName = clazz.getName().substring(clazz.getName().lastIndexOf(".")+1).toLowerCase();
            Field[] fields = clazz.getDeclaredFields();
            StringBuilder sql = new StringBuilder();
            sql.append("select * from ").append(tName);

            connection = DATASOURCE.getConnection();
            statement = connection.prepareStatement(sql.toString());
            resultSet = statement.executeQuery();
            while (resultSet.next()){
                // 定义 Object
                Object object = clazz.newInstance();
                for (int i = 0; i < fields.length; i++) {
                    fields[i].setAccessible(true);
                    if(fields[i].getType() == int.class){
                        fields[i].setInt((T) object,resultSet.getInt(fields[i].getName()));
                    } else if(fields[i].getType() == String.class){
                        fields[i].set(object, resultSet.getString(fields[i].getName()));
                    }
                }
                objs.add((T)object);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } finally {
            closeAll(connection,statement,resultSet);
        }

        return objs;
    }

    /**
     * 根据id返回一个数据
     * @param id
     * @return
     */
    @Override
    public T selectOne(Class clazz,int id) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet =null;
        Object object = null;
//        List<T> objs = new ArrayList<>();

        String tName = clazz.getName().substring(clazz.getName()
            .lastIndexOf(".") + 1).toLowerCase();
        // 获取 clazz 类中所有字段名称，不包含父类
        Field[] fields = clazz.getDeclaredFields();
        StringBuilder sql = new StringBuilder();
        sql.append("select * from ").append(tName).append(" where id=?");

        try {
            connection = DATASOURCE.getConnection();
            statement = connection.prepareStatement(sql.toString());
            statement.setInt(1,id);
            resultSet = statement.executeQuery();
            resultSet.next();
            // 定义 Object
            object = clazz.newInstance();
            for (int i = 0; i < fields.length ; i++) {
                fields[i].setAccessible(true);
                if(fields[i].getType() == int.class){
                    // 获取到某个字段的value
                    fields[i].setInt(object, resultSet.getInt(fields[i].getName()));
                } else if(fields[i].getType() == String.class){
                    // 获取到某个字段的value
                    fields[i].set(object, resultSet.getString(fields[i].getName()));
                }
            }
//            objs.add((T)object);
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } finally {
            closeAll(connection,statement,null);
        }
        return (T)object;
    }

    /**
     * 更新数据
     * @param t
     * @return
     */
    @Override
    public int update(T t) {
        return 0;
    }
}
